/**
 * Clase Estadísticas: Contiene las funciones para obtener las estadísticas
 * del uso del Proxy.
 *
 * Autores: Christian Chomiak (05-38034)
 *          Miguel De Los Ríos (05-38084)
 */
package kraken;

import java.util.*;
import java.io.*;

/**
 *
 * @author Miguel De Los Ríos
 */
public class Estadistica implements Comparable {

    /*
     * Un objeto de la clase estadística como tal sirve para calcular los topsites,
     * sites_users, users_sites y date_time y denied se calculan con métodos estáticos
     */
    private String host;
    private int num_visitas;
    // Clave: Usuario que visita, valores: Horas en las que visita
    private Hashtable<String, List<String>> visitas_usuarios;

    public Estadistica(String host, String usuario, String fecha_hora) {
        this.host = host;
        num_visitas = 1;
        visitas_usuarios = new Hashtable<String, List<String>>();
        List<String> fechas = new ArrayList<String>();
        fechas.add(fecha_hora);
        visitas_usuarios.put(usuario, fechas);
    }

    public Estadistica(String host) {
        this.host = host;
    }

    public Estadistica(String host, String usuario, List<String> fechas_horas) {
        this.host = host;
        num_visitas = 1;
        visitas_usuarios = new Hashtable<String, List<String>>();
        visitas_usuarios.put(usuario, fechas_horas);
    }

    public String getHost(){
        return this.host;
    }

    public int getNumVisitas(){
        return this.num_visitas;
    }

    public Hashtable<String, List<String>> getVisitas(){
        return this.visitas_usuarios;
    }

    //Busca si un host ya se encuentra en una lista de estadisticas. De ser así,
    //retorna el índice donde se encuentra, en caso contrario retorna -1.
    private static int BuscarHost(String host, List<Estadistica> Estadisticas) {
        for (int i = 0; i < Estadisticas.size(); i++) {
            if (Estadisticas.get(i).host.equals(host)) {
                return i;
            }
        }
        return -1;
    }

    // Lee el log
    private static List<String[]> LeerLog() {
        try {
            List<String[]> lineas = new ArrayList<String[]>();

            FileInputStream fstream = new FileInputStream("Resources/log.txt");
            DataInputStream in = new DataInputStream(fstream);
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            String linea;

            while ((linea = reader.readLine()) != null) {
                lineas.add(linea.split(" "));
            }
            return lineas;
        } catch (IOException e) {
            System.err.println("Error leyendo el log");
            return null;
        }
    }

    //Obtiene la lista de estadísticas a ser usada por los comandos. Si el flag
    // de prohibidas es falso, se buscan las permitidas, si no, se buscan las prohibidas.
    private static List<Estadistica> GetEstadisticas(boolean buscar_prohibidas) {
        List<String[]> lineas_log = LeerLog();
        if (lineas_log != null) {
            List<Estadistica> Estadisticas = new ArrayList<Estadistica>();

            for (int i = 0; i < lineas_log.size(); i++) {
                String[] linea = lineas_log.get(i);
                if(linea.length > 5){
                String status = linea[0];
                String host = linea[1];
                String path = linea[2];
                String usuario = linea[3];
                String fecha_hora = linea[4] + " " + linea[5];
                int pos;

                if((buscar_prohibidas && status.equals("Prohibida")) || (!buscar_prohibidas && status.equals("Permitida"))){
                if((pos = BuscarHost(host, Estadisticas)) != -1){
                    Estadisticas.get(pos).num_visitas++;
                    List<String> fechas;
                    if(Estadisticas.get(pos).visitas_usuarios.containsKey(usuario))
                       fechas = Estadisticas.get(pos).visitas_usuarios.get(usuario);
                    else
                       fechas = new ArrayList<String>();
                    fechas.add(fecha_hora);
                    Estadisticas.get(pos).visitas_usuarios.put(usuario, fechas);
                }else
                    Estadisticas.add(new Estadistica(host, usuario, fecha_hora));
                }
                }
            }

            return Estadisticas;

        } else {
            return null;
        }
    }

    //TopSites
    public static List<Estadistica> TopSites(){
        List<Estadistica> Stats = GetEstadisticas(false);
        Collections.sort(Stats);
        if(Stats.size() >= 10)
            return Stats.subList(0, 10);
        else
            return Stats;
    }

    //Sites_users
    public static List<Estadistica> SitesUsers(){
        return GetEstadisticas(false);
    }

    //users_sites
    public static List<Estadistica> UserSites(String ip){
        List<Estadistica> Stats = GetEstadisticas(false);
        List<Estadistica> UserStats = new ArrayList<Estadistica>();
        for(int i = 0; i < Stats.size(); i++){
            Estadistica stat = Stats.get(i);
            if(stat.visitas_usuarios.containsKey(ip)){
                //Crea una estadistica solo con la informacion del usuario
                Estadistica userStat = new Estadistica(stat.host, ip, stat.visitas_usuarios.get(ip));
                userStat.num_visitas = stat.visitas_usuarios.get(ip).size();
                UserStats.add(userStat);
            }
        }
        return UserStats;
    }

    public static List<Estadistica> denied(){
        return GetEstadisticas(true);
    }

    //Métodos para implementar comparable
    public int compareTo(Object o){
        Estadistica stat = (Estadistica) o;
        return stat.num_visitas - this.num_visitas;
    }
}
